 <script setup lang="ts">
import {ref, nextTick, computed, onMounted, onUnmounted, watch } from 'vue'

/**
 * 定义组件接收的属性
 */
const props = defineProps<{
  modelValue: boolean
}>()
const isMobileOrTablet = computed(() => {
  return window.innerWidth <= 768
})
/**
 * 定义组件触发的事件
 */
const emit = defineEmits<{
  (e: 'update:modelValue', value: boolean): void
}>()

/**
 * 计算属性，用于双向绑定 visible 和 modelValue
 * @returns 当前 modelValue 的值
 */
const visible = computed({
  get: () => props.modelValue,
  set: (val) => emit('update:modelValue', val)
})

/**
 * 输入框文本内容
 */
const inputText = ref('')


/**
 * 聊天记录数组，每条记录包含角色(user/ai)、内容和附件信息
 */
const chatHistory = ref<{ role: 'user' | 'ai'; content: string,attachments?:{ type: string, data: string} }[]>([])

/**
 * 标记是否正在发送消息
 */
const sending = ref(false)

// 模型列表
const models = [
  {label: 'Qwen-Max（快）', value: 'qwen-max',speed: 600},
  {label: 'GPT-4（强）', value: 'gpt-4' ,speed: 1200},
  {label: 'Claude-3（平衡）', value: 'claude-3', speed: 900}
]

/**
 * 上次选择的模型，默认为 qwen-max
 */
const lastModel = localStorage.getItem('ai_selected_model') || 'qwen-max'

/**
 * 当前选中的模型
 */
const selectedModel = ref(lastModel)

/**
 * 自动模式开关状态
 */
const autoMode = ref(localStorage.getItem('ai_auto_mode') === 'true')

/**
 * 推荐模型计算属性，根据速度推荐最快的模型
 * @returns 推荐模型的 value 值
 */
const recommendedModel = computed(() => {
  return models.reduce((a,b) => (a.speed > b.speed ? a : b)).value
})

/**
 * 实际生效的模型，自动模式下使用推荐模型，否则使用手动选择的模型
 * @returns 生效模型的 value 值
 */
const effectiveModel = computed(() => {
  return autoMode.value ? recommendedModel.value : selectedModel.value
})

/**
 * 是否处于拖拽状态
 */
const isDragging = ref(false)

/**
 * 鼠标相对于聊天窗口左上角的偏移量 X
 */
const offsetX = ref(0)

/**
 * 鼠标相对于聊天窗口左上角的偏移量 Y
 */
const offsetY = ref(0)

/**
 * 聊天窗口的位置坐标
 */
const position = ref({x: window.innerWidth -540, y: 100})

/**
 * 聊天框 DOM 引用
 */
const chatBox = ref<HTMLDivElement | null>(null)

/**
 * 将聊天框滚动到底部
 */
const scrollToBottom = () => {
  nextTick(() => {
    if (chatBox.value) {
      chatBox.value.scrollTop = chatBox.value.scrollHeight
    }
  })
}

/**
 * 使用浏览器语音合成功能朗读文本
 * @param text 要朗读的文本内容
 */
const speak = (text: string) => {
  if ('speechSynthesis' in window) {
    const utterance = new SpeechSynthesisUtterance(text)
    utterance.lang = 'zh-CN'
    utterance.rate = 0.9
    speechSynthesis.cancel() // 避免堆积
    speechSynthesis.speak(utterance)
  }
}

/**
 * 处理发送消息逻辑
 */
const handleSend = async () => {
  const text = inputText.value.trim()
  if (!text || sending.value) return

  sending.value = true
  inputText.value = ''
  chatHistory.value.push({role: 'user', content: text})
  scrollToBottom()

  // 模拟 AI 响应
  setTimeout(() => {
    const reply = `我是 ${selectedModel.value}，已收到：“${text}”。这是模拟回复。`
    chatHistory.value.push({role: 'ai', content: reply})
    scrollToBottom()
    speak(reply)
    sending.value = false
  }, 800 + Math.random() * 500)
}

/**
 * 关闭聊天窗口
 */
const handleClose = () => {
  emit('update:modelValue', false)
  //inputText.value= ''
  if (inputRef.value){
    inputRef.value.blur()
  }
}

/**
 * 文件输入框引用
 */
const fileInput = ref<HTMLInputElement | null>(null)
const handleFileChange = (event: Event) => {
  const target = event.target as HTMLInputElement
  const files = target.files
  if (files && files.length > 0){
    const file = files[0]
    const reader = new FileReader()
    if (file.type.startsWith('image/')){
      reader.onload = (e) => {
        const url = e.target?.result as string
        chatHistory.value.push({role: 'user', content:`上传了图片：${file.name} `, attachments:{type: 'image', data: url}})
        processImageWithAI(url)
      }
      reader.readAsDataURL(file)
    }else{
      chatHistory.value.push({role: 'user', content:`上传了文件：${file.name} （${formatFileSize(file.size)}）`})
      processFileWithAI(file)
    }
    target.value = ''
  }
}
const handleFileInputChange = (event: Event) => {
  handleFileChange(event)
}
/**
 * 触发文件上传点击事件
 */
const handleFileUploadClick = () => {
  fileInput.value?.click()
}
const handleImageUploadClick = () => {
  fileInput.value.accept = 'image/*'
  fileInput.value.value = ''
  fileInput.value?.click()
}
const handleFileUpload = () => {
  if (fileInput.value){
    //fileInput.value.accept = ".pdf,.doc,.docx,.xls,.xlsx,.ppt,.pptx,.txt,.rtf,.csv,.ods,.odt,.odp,application/pdf,application/msword,application/vnd.ms-excel,application/vnd.ms-powerpoint,application/vnd.openxmlformats-officedocument.wordprocessingml.document,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,application/vnd.openxmlformats-officedocument.presentationml.presentation,text/plain,text/rtf,application/vnd.oasis.opendocument.spreadsheet,application/vnd.oasis.opendocument.text,application/vnd.oasis.opendocument.presentation";
    fileInput.value.value = ''
    fileInput.value.click();
  }
}
const inputRef = ref<HTMLInputElement | null>(null)
/**
 * 处理文件上传事件
 * @param event 文件上传事件对象
 */
const handleFileUpload1 = (event: Event) => {
  const target = event.target as HTMLInputElement
  const files = target.files
  if (files && files.length > 0){
    const file = files[0]
    const reader = new FileReader()
    if (file.type.startsWith('image/')){
      reader.onload = (e) => {
        const url = e.target?.result as string
        chatHistory.value.push({role: 'user', content:`上传了图片：${file.name} `, attachments:{type: 'image', data: url}})
        processImageWithAI(url)
      }
      reader.readAsDataURL(file)
    }else {
      chatHistory.value.push({role: 'user', content:`上传了文件：${file.name} (${formatFileSize(file.size)}) `})
      processFileWithAI(file)
    }
    target.value = ''
  }
}

/**
 * 处理图像文件的 AI 分析
 * @param imageData 图像数据 URL
 */
const processImageWithAI = (imageData: string) => {
  setTimeout(() => {
    chatHistory.value.push({role: 'ai', content: `我已经分析了您上传的图片。这是一张示例图片，包含一些视觉元素。`})
    scrollToBottom()
  },1000)
}

/**
 * 处理普通文件的 AI 处理
 * @param file 上传的文件对象
 */
const processFileWithAI = (file: File) => {
  setTimeout(() => {
    chatHistory.value.push({role: 'ai', content: `已接收文件"${file.name}"（${file.type}，${formatFileSize(file.size)}）`})
    scrollToBottom()
  },1000)
}

/**
 * 格式化文件大小显示
 * @param bytes 文件字节数
 * @returns 格式化后的文件大小字符串
 */
const formatFileSize = (bytes: number) : string => {
  if (bytes < 1024)  return  bytes+'bytes'
  else if(bytes < 1048576) return (bytes/1024).toFixed(1)+'KB'
  else return (bytes/1048576).toFixed(1)+'MB'
}

/**
 * 处理模型选择变更
 * @param modelValue 新选择的模型值
 */
const  handleModelSelect = (modelValue: string) => {
  selectedModel.value = modelValue
  autoMode.value = false
  saveModelPreference()
}

/**
 * 切换自动模式状态
 */
const toggleAutoMode = () => {
  autoMode.value = !autoMode.value
}

/**
 * 保存模型偏好设置到本地存储
 */
const saveModelPreference = () => {
  localStorage.setItem('ai_selected_model', selectedModel.value)
  localStorage.setItem('ai_auto_mode', String(autoMode.value))
}

/**
 * 开始拖拽操作
 * @param e 鼠标按下事件对象
 */
const startDrag = (e: MouseEvent) => {
  isDragging.value = true
  offsetX.value = e.clientX - position.value.x
  offsetY.value = e.clientY - position.value.y
  e.preventDefault()
}

/**
 * 拖拽过程中更新位置
 * @param e 鼠标移动事件对象
 */
const onDrag = (e: MouseEvent) => {
  if (!isDragging.value) return
  position.value.x = e.clientX - offsetX.value
  position.value.y = e.clientY - offsetY.value
  position.value.x = Math.max(0, Math.min(window.innerWidth - 520, position.value.x))
  position.value.y = Math.max(0, Math.min(window.innerHeight - 600, position.value.y))
}

/**
 * 结束拖拽操作
 */
const stopDrag = () => {
  isDragging.value = false
}
const handleOverlayClock = () => {
  emit('update:modelValue', false)
  //inputText.value = ''
  if (inputRef.value){
    inputRef.value.blur()
  }
}
const resetInputState = () => {
  //inputText.value = ''
  nextTick(() => {
    if (inputRef.value){
      inputRef.value.focus()
    }
  })
}
// const  containerWidth = computed(() => isMobile.value ? window.innerWidth - 20 : 520)
// const  containerHeight = computed(() => isMobile.value ? window.innerHeight - 20 : 600)
// const  isMobile = computed(() =>  window.innerWidth <= 768)
/**
 * 组件挂载时执行初始化操作
 */
onMounted(() => {
  chatHistory.value.push({
    role: 'ai',
    content: '你好！我是你的智能助手，可提醒生日、离职等事项。有什么我可以帮您？'
  })
  scrollToBottom()

  // 监听键盘事件
  const handleKeyDown = (e: KeyboardEvent) => {
    // Ctrl+Enter 发送消息
    if (e.ctrlKey && e.key === 'Enter' && props.modelValue) {
      e.preventDefault();
      handleSend();
    }
  };

  document.addEventListener('keydown', handleKeyDown);

  return () => {
    document.removeEventListener('mousemove', onDrag)
    document.removeEventListener('mouseup', stopDrag)
    document.removeEventListener('keydown', handleKeyDown);
  };
})

/**
 * 组件卸载时清理资源
 */
onUnmounted(() => {
  document.removeEventListener('keydown', ()=>{});
})
watch(() => props.modelValue, (newVal) => {
  if (newVal){
    resetInputState()
  }
})
</script>


<template>
<!--  left: position.x + 'px',
  top: position.y + 'px'}"
  :style="{
    left: `${Math.max(0, Math.min(window.innerWidth - containerWidth, position.x))} px`,
    top: `${Math.max(0, Math.min(window.innerHeight - containerHeight, position.y))} px`,
    width: `${containerWidth}px`,
    height: `${containerHeight}px`
       }"-->
  <div class="ai-chat-overlay" @click="handleOverlayClock">
  <div class="ai-chat-container"
       :style="{ left: position.x + 'px',top: position.y + 'px'}"
       @mousedown="!isMobileOrTablet ? startDrag :  undefined "
       @mousemove="!isMobileOrTablet ? onDrag :  undefined "
       @mouseup="!isMobileOrTablet ? stopDrag :  undefined" @click.stop>
    <!-- 聊天窗口容器，支持拖拽移动位置 -->
    <div class="ai-chat-header">
      <!-- 头部标题与关闭按钮 -->
      <span>🤖 AI 助手</span>
      <el-button
          type="danger"
          icon="Close"
          circle
          size="small"
          @click="handleClose"
          class="close-btn"
      />
    </div>

    <!-- 模型选择区 -->
    <div class="model-selector">
      <div class="model-cards">
        <!-- 遍历显示所有可用模型卡片，点击可切换选中状态 -->
        <div v-for="m in models" :key="m.value" class="model-card" :class="{ active: !autoMode && selectedModel === m.value}" @click="handleModelSelect(m.value)">
          {{ m.label.split('(')[0]}}
        </div>
      </div>
      <div class="auto-toggle">
        <!-- 自动模式开关及推荐提示信息 -->
        <el-checkbox v-model="autoMode" @change="saveModelPreference">自动选择模型</el-checkbox>
        <span class="recommend-tip" v-if="autoMode">
          推荐：{{ models.find(m => m.value === selectedModel)?.label.split('(')[0]}}
        </span>
      </div>
    </div>

    <!-- 聊天区域 -->
    <div ref="chatBox" class="chat-box">
      <!-- 显示聊天历史记录，每条消息根据角色区分样式 -->
      <div v-for="(msg, idx) in chatHistory" :key="idx" class="chat-message">
        <div :class="['msg-bubble', msg.role]">
          {{ msg.content }}
          <!-- 若存在附件则展示预览（当前仅支持图片） -->
          <div v-if="msg.attachment" class="attachment-preview">
            <img v-if="msg.attachment.type === 'image'" :src="msg.attachment.data" alt="Preview"/>
          </div>
        </div>
      </div>
    </div>

    <!-- 输入区 -->
    <div class="input-area">
      <!-- 文本输入框，支持回车发送、情况功能 -->
      <el-input ref="inputRef" v-model="inputText" @keyup.enter="handleSend" placeholder="输入消息...(Ctrl+Enter发送)"
                clearable class="input-field">
      <template #suffix>
        <el-button link icon="Picture" @click="handleImageUploadClick" class="icon-btn"/>
        <el-button link icon="upload-filled" @click="handleFileUploadClick" class="icon-btn"/>
      </template>
      </el-input>
      <el-button type="primary" @click="handleSend" :loading="sending" class="send-btn" icon="promotion">发送</el-button>
      <input type="file" ref="fileInput" @change="handleFileInputChange"
             accept="*/.pdf,.doc,.docx,.xls,.xlsx,.ppt,.pptx,.txt,.rtf,.csv,.ods,.odt,.odp,application/pdf,application/msword,application/vnd.ms-excel,application/vnd.ms-powerpoint,application/vnd.openxmlformats-officedocument.wordprocessingml.document,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,application/vnd.openxmlformats-officedocument.presentationml.presentation,text/plain,text/rtf,application/vnd.oasis.opendocument.spreadsheet,application/vnd.oasis.opendocument.text,application/vnd.oasis.opendocument.presentation"
             style="display: none"/>
   </div>
  </div>
  </div>
</template>


<style scoped>
.ai-chat-container{
  width: 520px !important;
  height: 600px !important;
  cursor: move !important;
  position: absolute !important;
}
.chat-box{
  height: calc(100% - 180px);
  overflow-y: auto;
  overflow-x: hidden;
}
/* 推荐提示文本样式：蓝色强调色 */
.recommend-tip {
  color: #409eff;
  font-weight: 500;
}
/* 模型下拉选择容器：水平居中对齐并留有间距 */
.model-select-container{
  display: flex;
  align-items: center;
  gap: 12px;
  width: 100%;
}

/* 下拉菜单样式：去除默认边框与背景，并保持聚焦时无变化 */
.model-select {
  flex: 1;
  font-size: 14px;
  color: white !important;
  outline: none !important;
  border: none !important;
  background: transparent !important;
}
.model-select:focus{
  box-shadow: none !important;
  border-color: transparent !important;
}
/* 下拉箭头图标颜色设置为白色 */
.model-select .el-select__caret{
  color: white !important;
}

/* 自定义下拉弹出层样式：深色主题风格 */
.custom-model-popper{
  background-color: #1a1a1a !important;
  border: 1px solid #333 !important;
  border-radius: 6px !important;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2) !important;
  max-width: 300px !important;
}

/* 自动推荐信息容器：显示辅助说明文字 */
.auto-recommend{
  display: flex;
  align-items: center;
  gap: 4px;
  font-size: 12px;
  color: #909399;
}

/* 推荐项标签样式：加粗灰色文字 */
.recommend-label {
  font-weight: 500;
  color: #333;
}

/* 推荐值样式：使用蓝色突出显示 */
.recommend-value{
  color: #409eff;
}

/* 弹出层内选项通用样式：统一内边距、字体大小与过渡动画 */
.custom-model-popper .el-select-dropdown__item {
  padding: 12px 16px !important;
  color: #e6e6e6 !important;
  font-size: 14px !important;
  transition: all  0.3s ease !important;
}

/* 鼠标悬停时选项变亮 */
.custom-model-popper .el-select-dropdown__item:hover {
  background-color: #2a2a2a !important;
  color: #fff !important;
}

/* 已选中项特殊背景色 */
.custom-model-popper .el-select-dropdown__item.selected {
  background-color: #2c3e50 !important;
  color: #fff !important;
}

/* 勾选图标样式：蓝色显示 */
.custom-model-popper .el-select-dropdown__item .el-icon-check {
  color: #409eff !important;
  font-size: 16px !important;
}

/* 描述性文字样式：小字号浅灰 */
.custom-model-popper .el-select-dropdown__item .model-description {
  font-size: 12px;
  color: #999;
  margin-top: 4px;
  line-height: 1.4;
}

/* 新模型标记样式：蓝底白字徽章 */
.custom-model-popper .el-select-dropdown__item .new-model-tag {
  background-color: #409eff;
  color: white;
  font-size: 10px;
  padding: 2px 6px;
  border-radius: 4px;
  margin-left: 8px;
}

/* 提示语样式：浅灰色细体 */
.auto-tip {
  font-size: 12px;
  color: #909399;
}


/* 附件预览区：图片最大尺寸控制与圆角 */
.attachment-preview{
  margin-top: 8px;
}

/* 输入控件容器：包含输入框和附加动作按钮 */
.input-controls {
  display: flex;
  align-items: center;
  gap: 8px;
  flex: 1;
  position: relative;
}



/* 动作按钮组容器：右侧对齐 */
.input-actions{
  display: flex;
  align-items: center;
  gap: 8px;
}

/* 多个动作按钮排列方式 */
.action-buttons {
  display: flex;
  gap: 8px;
  margin-right: 8px;
}


/* 图标按钮基础样式：默认灰色，悬停变为蓝色 */
.icon-btn {
  color: #606266;
  &:hover {
    color: #409eff;
  }

}

/* 发送按钮容器：居中对齐 */
.send-button{
  display: flex;
  align-items: center;
  justify-content: center;
}
@media (max-width: 768px) {
  .ai-chat-container{
    width: calc(100vw - 20px) !important;
    height: calc(100vh - 20px) !important;
    left: 20px !important;
    top: 50% !important;
    transform: translateY(-50%) !important;
    cursor: default !important;
    position: fixed !important;
  }
  .chat-box{
    height: calc(100% - 180px);
  }
}
</style>
